package com.motu.monstercity.server.game.logic;

import com.motu.monstercity.protocol.Common.PBUserData;
import com.motu.monstercity.protocol.CsGameSystem;
import com.motu.monstercity.server.game.base.ProtoDataUtils;
import com.motu.monstercity.server.game.commondata.act.Act;
import com.motu.monstercity.server.game.commondata.act.ActDay;
import com.motu.monstercity.server.game.commondata.act.ActTask;
import com.motu.monstercity.server.game.commondata.maintask.MainTaskConstant;
import com.motu.monstercity.server.game.commondata.shop.Shop;
import com.motu.monstercity.server.game.userdata.*;
import com.motu.vertx.module.utility.model.BaseModel;
import com.motu.vertx.module.utility.model.EntityManager;
import com.motu.vertx.module.utility.toolset.TimeUtils;
import com.motu.vertx.module.utility.toolset.Tool;
import io.vertx.core.json.JsonArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;

public class ActDaysManager extends ActDaysUserData {
    private static Logger logger = LoggerFactory.getLogger(ActDaysManager.class);

    /**
     * 更新主题任务任务进度
     */
    public static void updateTask(PBUserData.Builder pbUserData, UserInfo userInfo, int taskId, long num, int param, boolean isAdd) {
        if (num <= 0) {
            return;
        }
//        long userId = userInfo.getId();
//        List<UserAct> userMotifActList = getUserMotifActList(userInfo, false);
//        for (UserAct userMotifAct : userMotifActList) {
//        }
        UserExtInfo userExtInfo = GameUser.getUserExtInfo(userInfo.getId());
        long newComerActId = getNewComerActId(userExtInfo);
        if (newComerActId > UserAct.NEWCOMER_ACT_ID_START) {
            updateTask(pbUserData, userInfo, newComerActId, taskId, num, param, isAdd);
        }
    }


    public static void updateTask(PBUserData.Builder pbUserData, UserInfo userInfo, long actId, int taskType, long value, int param, boolean isAdd) {
        int taskId = getTaskId(taskType, param);
        long userId = userInfo.getId();
//        long actId = userAct.getActId();
        int groupId = 0;
        int day = 1;
        if (actId > UserAct.NEWCOMER_ACT_ID_START) {
            UserAct userAct = getUserMotifAct(userInfo.getId(), actId);
            if (userAct == null || !userAct.isOpen()) {
                return;
            }
            groupId = userAct.getGroupId();
            day = userAct.getDiffDay();
        } else {
            Act act = ActManager.getAct(actId);
            if (act == null || !act.isStart(userInfo.getServerId())) {
                return;
            }
            groupId = act.getActParamValue();
            day = act.getDiffDays();
        }
        List<ActDay> actDayList = getActDaysByGroupId(groupId);
        List<ActTask> taskList = new ArrayList<>();
        Map<Integer, Integer> groupOpenDayMap = new HashMap<>();
        for (ActDay actDay : actDayList) {
//            if (actDay.getDay() > day) {
//                break;
//            }
            groupOpenDayMap.put(actDay.getTaskGroupId(), actDay.getDay());
            List<ActTask> taskList0 = getRankActTasksByGroupId(actDay.getTaskGroupId(), taskType, param);
            if (taskList0 == null || taskList0.isEmpty()) {
                continue;
            }
            taskList.addAll(taskList0);
        }
        if (taskList.isEmpty()) {
            return;
        }
        ActTask actTask = taskList.stream().min(Comparator.comparing(ActTask::getId)).orElse(null);
        int openDay = groupOpenDayMap.getOrDefault(actTask.getTaskGroupId(), 0);
        if (openDay > day && !actTask.isFirstDayOpen()) {
            return;
        }
        UserActDayTask userActDayTask = getUserActDayTask(userId, actId, taskId);
        if (userActDayTask == null) {
            userActDayTask = new UserActDayTask(userId, actId, taskId);
            userActDayTask.doCreate();
        }
        boolean update = false;
        if (isAdd) {
            userActDayTask.addCurP(value);
            update = true;
        } else {
            if (value > userActDayTask.getCurP()) {
                userActDayTask.putCurP(value);
                update = true;
            }
        }
        if (update) {
            userActDayTask.update();
            ProtoDataUtils.updatePBUserData(pbUserData, userActDayTask);
        }
    }

    public static void checkTaskRedPoint(UserInfo userInfo, UserActDayTask userActDayTask, long actId, long oldP) {
        boolean hasRedPoint = false;
        int groupId = 0;
        int day = 1;
        if (actId > UserAct.NEWCOMER_ACT_ID_START) {
            UserAct userAct = getUserMotifAct(userInfo.getId(), actId);
            if (userAct == null || !userAct.isOpen()) {
                return;
            }
            groupId = userAct.getGroupId();
            day = userAct.getDiffDay();
        } else {
            Act act = ActManager.getAct(actId);
            if (act == null || !act.isStart(userInfo.getServerId())) {
                return;
            }
            groupId = act.getActParamValue();
            day = act.getDiffDays();
        }
        List<ActDay> actDayList = getActDaysByGroupId(groupId);
        final int curDay = day;
        List<Integer> dayList = new ArrayList<>();
        List<ActDay> list = actDayList.stream().filter(a -> a.getDay() <= curDay).toList();
        JsonArray recvTasks = userActDayTask.getGetRewardArray();
        for (ActDay actDay1 : list) {
            List<ActTask> taskList = getActTasksByGroupId(actDay1.getTaskGroupId());
            for (ActTask actTask : taskList) {
                if (oldP >= actTask.getNum1()) {
                    continue;
                }
                if (userActDayTask.getCurP() >= actTask.getNum1() && !recvTasks.contains(actTask.getId())) {
                    hasRedPoint = true;
                    dayList.add(actDay1.getDay());
                    break;
                }
            }
        }
    }

    private static void updateTask(PBUserData.Builder pbUserData, long userId, long actId, int taskType, long value, int param, boolean isAdd) {
        int taskId = getTaskId(taskType, param);
        UserActDayTask userActDayTask = getUserActDayTask(userId, actId, taskId);
        if (userActDayTask == null) {
            userActDayTask = new UserActDayTask(userId, actId, taskId);
            userActDayTask.doCreate();
        }
        boolean update = false;
        if (isAdd) {
            userActDayTask.addCurP(value);
            update = true;
        } else {
            if (value > userActDayTask.getCurP()) {
                userActDayTask.putCurP(value);
                update = true;
            }
        }
        if (update) {
            userActDayTask.update();
            ProtoDataUtils.updatePBUserData(pbUserData, userActDayTask);
        }
    }

    public static int getTaskId(int taskType, int param) {
        if (param == 0) {
            return taskType;
        }
        return taskType * 1000000 + param;
    }

    public static void resetActData(UserAct userActDays) {
        userActDays.putIntegralReward("");
        userActDays.putIntegralScore(0);
        userActDays.putLoginTime(0L);
        userActDays.putIntegralScore(0);
        userActDays.putBuyGift("");
        long actId = userActDays.getActId();
        if (actId > 0) { // 删除任务
            EntityManager.delEntity(UserActDayTask.class, userActDays.getId());
        }
    }

    /**
     * 初始化任务数据
     */
    public static void initTask(UserInfo userInfo, UserAct act) {
//        if (!act.isGetRewardTime(userInfo.getServerId())) {
//            return;
//        }
        long userId = userInfo.getId();
        int groupId = act.getGroupId();
        long curTime = TimeUtils.getCurTime();
        List<UserActDayTask> userActDayTaskList = getUserActDayTasks(userId, act.getId());
        Map<Integer, UserActDayTask> taskMap = userActDayTaskList.stream().collect(Collectors.toMap(UserActDayTask::getTaskType, t -> t));
        int day = TimeUtils.getDiffDay(act.getStartTime(), curTime);
        List<ActDay> actDayList = getActDaysByGroupId(groupId);
        List<ActTask> actTaskList = new ArrayList<>();
        Map<Integer, Integer> groupOpenDayMap = new HashMap<>();
        for (ActDay actDay : actDayList) {
//            if (actDay.getDay() > day) {
//                break;
//            }
            groupOpenDayMap.put(actDay.getTaskGroupId(), actDay.getDay());
            List<ActTask> actTaskList0 = getActTasksByGroupId(actDay.getTaskGroupId());
            if (actTaskList0 != null && !actTaskList0.isEmpty()) {
                actTaskList.addAll(actTaskList0);
            }
        }
        for (ActTask actTask : actTaskList) {
            int taskType = getTaskId(actTask.getTaskType(), actTask.getNum2());
            if (taskMap.containsKey(taskType)) { // 如果已经有任务则忽略
                continue;
            }
            int openDay = groupOpenDayMap.getOrDefault(actTask.getTaskGroupId(), 0);
            if (openDay > day && !actTask.isFirstDayOpen()) {
                continue;
            }
            if (actTask.isGetMainTask()) { // 如果需要继承主线任务就执行下面的操作
                long taskValue = MainTaskManager.getTaskValue(userId, actTask.getType(), actTask.getNum2());
                if (taskValue > 0) { // 如果有这个主线任务就直接复制过来
                    UserActDayTask userActDayTask = new UserActDayTask(userId, act.getId(), taskType);
                    userActDayTask.putCurP(taskValue);
                    userActDayTask.doCreate();
                    taskMap.put(taskType, userActDayTask); // 保存好后加到缓存里面供下次判断
                }
            }
        }
    }

    public static long[] getActDayInfo(UserInfo userInfo) {
        UserExtInfo userExtInfo = GameUser.getUserExtInfo(userInfo.getId());
        long actId = getNewComerActId(userExtInfo);
        int groupId = 0;
        long[] actInfo = new long[2];
        actInfo[0] = actId;
        if (actId > UserAct.NEWCOMER_ACT_ID_START) {
            UserAct userAct = getUserMotifAct(userInfo.getId(), actId);
            if (userAct == null || !userAct.isOpen()) {
                return actInfo;
            }
            groupId = userAct.getGroupId();
        } else {
            Act act = ActManager.getAct(actId);
            if (act == null || !act.isStart(userInfo.getServerId())) {
                return actInfo;
            }
            groupId = act.getActParamValue();
        }
        actInfo[1] = groupId;
        return actInfo;
    }

    public static <T extends BaseModel> void updateOuterTask(UserInfo userInfo, PBUserData.Builder pbUserData, int taskType, List<T> modelList, DayTaskInterface<T> function) {
        long[] actInfo = getActDayInfo(userInfo);
        long actId = actInfo[0];
        if (actId == 0) {
            return;
        }
        long userId = userInfo.getId();
        int groupId = (int) actInfo[1];
        List<ActTask> dayList = getActTasksByActGroupId(groupId, taskType);
        if (dayList == null || dayList.isEmpty()) {
            return;
        }
        for (ActTask actTask : dayList) {
            int param = actTask.getNum2();
            int num = function.apply(modelList, param);
            updateTask(pbUserData, userId, actId, taskType, num, param, false);
        }
    }

    public static void updatePartnerTask(UserInfo userInfo, PBUserData.Builder pbUserData, List<UserPartner> partnerList) {
        long[] actInfo = getActDayInfo(userInfo);
        long actId = actInfo[0];
        if (actId == 0) {
            return;
        }
        long userId = userInfo.getId();
        int groupId = (int) actInfo[1];
        List<ActTask> dayList = getActTasksByActGroupId(groupId, MainTaskConstant.TASK_TYPE_107);
        if (dayList == null || dayList.isEmpty()) {
            return;
        }
        for (ActTask actTask : dayList) {
            int param = actTask.getNum2();
            int parterNum = PartnerManager.countPartnerNumByLevel(partnerList, param);
            updateTask(pbUserData, userId, actId, MainTaskConstant.TASK_TYPE_107, parterNum, param, false);
        }
    }

    public static void updatBuildTask(UserInfo userInfo, PBUserData.Builder pbUserData, List<UserBuild> buildList) {
        long[] actInfo = getActDayInfo(userInfo);
        long actId = actInfo[0];
        if (actId == 0) {
            return;
        }
        long userId = userInfo.getId();
        int groupId = (int) actInfo[1];
        List<ActTask> dayList = getActTasksByActGroupId(groupId, MainTaskConstant.TASK_TYPE_123);
        if (dayList == null || dayList.isEmpty()) {
            return;
        }
        for (ActTask actTask : dayList) {
            int param = actTask.getNum2();
            int num = BuildManager.countBuildNumByLevel(buildList, param);
            updateTask(pbUserData, userId, actId, MainTaskConstant.TASK_TYPE_123, num, param, false);
        }
    }

    public static void updateWeaponTask(UserInfo userInfo, PBUserData.Builder pbUserData, List<UserWeapon> weaponList) {
        long[] actInfo = getActDayInfo(userInfo);
        long actId = actInfo[0];
        if (actId == 0) {
            return;
        }
        long userId = userInfo.getId();
        int groupId = (int) actInfo[1];
        List<ActTask> dayList = getActTasksByActGroupId(groupId, MainTaskConstant.TASK_TYPE_111);
        if (dayList == null || dayList.isEmpty()) {
            return;
        }
        for (ActTask actTask : dayList) {
            int param = actTask.getNum2();
            int num = PartnerManager.countWeaponTalent(weaponList, param);
            updateTask(pbUserData, userId, actId, MainTaskConstant.TASK_TYPE_111, num, param, false);
        }
    }

    public static void doSevenDaysActEndLogic(Act act) {
        try {
            logger.info("###doSevenDaysActEndLogic actId = " + act.getId());
            EntityManager.delEntity(UserActDayTask.class);
        } catch (Exception e) {
            String errMsg = Tool.getException(e);
            logger.error("###doSevenDaysActEndLogic error:" + errMsg);
//            GameManager.saveServerCrashLog(999999, errMsg);
        }
    }

    /**
     * 新建没有的主题活动
     *
     * @param userInfo
     */
    public static List<UserAct> createAllUserAct(UserInfo userInfo) {
        long userId = userInfo.getId();
        List<Long> actIdList = new ArrayList<>(); // 限时主题活动id列表
        long newcomerActId = 0L; // 新手主题活动id
        List<UserAct> userMotifActList = ActManager.getUserActList(userId);
        for (UserAct userMotifAct : userMotifActList) {
            if (userMotifAct.getActId() < UserAct.NEWCOMER_ACT_ID_START) {
            } else if (userMotifAct.getActId() < UserAct.CUSTOM_ACT_ID_START) {
                newcomerActId = userMotifAct.getActId();
            }
            actIdList.add(userMotifAct.getActId());
        }
        // 新增新手主题活动
        if (newcomerActId == 0) {
            UserAct userMotifAct = getUserMotifAct(userId, UserAct.NEWCOMER_ACT_ID_START);
            if (userMotifAct != null) {
                userMotifActList.add(userMotifAct);
            }
        }
//        // 新增限时主题活动
//        ConcurrentHashMap<Long, Act> actList = ActManager.getActList();
//        for (Act act : actList.values()) {
//            if (!act.isStart(userInfo.getServerId())) {
//                continue;
//            }
//            if (act.getType() != Act.ACT_TYPE_MOTIF) {
//                continue;
//            }
//            if (act.getType() == Act.ACT_TYPE_MOTIF
//                    && !MotifManager.isNewShow(userInfo, act.getActParamArray())) {
//                continue;
//            }
//            if (actIdList.contains(act.getId())) {
//                continue;
//            }
//            UserMotifAct userMotifAct = MotifManager.getUserMotifAct(userId, act.getId());
//            if (userMotifAct != null) {
//                actIdList.add(act.getId());
//                userMotifActList.add(userMotifAct);
//            }
//        }
        return userMotifActList;
        // 初始化主题活动的任务
        //MotifManager.initTaskCurp(userInfo, userMotifActList);
    }

    /**
     * 获取用户开启中的主题活动数据列表
     *
     * @param isJudgeNewShow 是否需要判断新手展示字段
     */
    public static List<UserAct> getUserMotifActList(UserInfo userInfo, boolean isJudgeNewShow) {
        List<UserAct> userMotifActList = new ArrayList<>();
        long userId = userInfo.getId();
        // 新建没有的所有主题活动
        List<UserAct> allUserMotifAct = createAllUserAct(userInfo);
        UserAct userNewcomerMotifAct = null;
        if (isJudgeNewShow) {
            for (UserAct userMotifAct : allUserMotifAct) {
                if (userMotifAct.isOpen() && userMotifAct.getActId() > UserAct.NEWCOMER_ACT_ID_START
                        && userMotifAct.getActId() < UserAct.CUSTOM_ACT_ID_START) {
                    userNewcomerMotifAct = userMotifAct;
                    break;
                }
            }
        }
        for (UserAct userMotifAct : allUserMotifAct) {
            if (userMotifAct.isOpen()) {
                if (isJudgeNewShow && userMotifAct.getActId() < UserAct.NEWCOMER_ACT_ID_START) {
                    Act act = ActManager.getAct(userMotifAct.getActId());
                    if (act != null && userNewcomerMotifAct != null) {
                        continue;
                    }
                }
                userMotifActList.add(userMotifAct);
            }
        }
        return userMotifActList;
    }

    public static boolean checkRedPoint(UserInfo userInfo, UserExtInfo userExtInfo, CsGameSystem.CSGameSystemRedPointResponse.Builder res_build) {
        long newComerActId = getNewComerActId(userExtInfo);
        if (newComerActId == 0) {
            return false;
        }
        UserAct userAct = getUserMotifAct(userExtInfo.getId(), newComerActId);
        boolean hasRedPoint = false;
        if (userAct != null) {
            CsGameSystem.RedPoint_ActDays.Builder redBuild = CsGameSystem.RedPoint_ActDays.newBuilder();
            int day = userAct.getDiffDay();
//            ActDay actDay = getActDaysByDay(userAct.getGroupId(), 1);
//            JsonArray rewardArray = userAct.getIntegralRewardArray();
//            int[] integralArr = actDay.getIntegralArray();
//            for (int i = 0; i < integralArr.length; i++) {
//                if (userAct.getIntegralScore() >= integralArr[i] && !rewardArray.contains(i)) {
//                    redBuild.addDays(actDay.getDay());
//                }
//            }
            initTask(userInfo, userAct);
            List<ActDay> actDayList = getActDaysByGroupId(userAct.getGroupId());
            List<ActDay> list = actDayList.stream().filter(a -> a.getDay() <= day).toList();
            JsonArray buyGift = userAct.getBuyGiftArray();
            for (ActDay actDay1 : list) {
                List<ActTask> taskList = getActTasksByGroupId(actDay1.getTaskGroupId());
                List<UserActDayTask> userActDayTaskList = getUserActDayTasks(userExtInfo.getId(), userAct.getActId());
                Map<Integer, UserActDayTask> userActDayTaskMap = userActDayTaskList.stream().collect(Collectors.toMap(UserActDayTask::getTaskType, t -> t));
                for (ActTask actTask : taskList) {
                    int taskType = actTask.getTaskType();
                    int taskId = getTaskId(taskType, actTask.getNum2());
                    if (!userActDayTaskMap.containsKey(taskId)) {
                        continue;
                    }
                    UserActDayTask userActDayTask = userActDayTaskMap.get(taskId);
                    JsonArray recvTasks = userActDayTask.getGetRewardArray();
                    if (userActDayTask.getCurP() >= actTask.getNum1() && !recvTasks.contains(actTask.getId())) {
                        hasRedPoint = true;
                        redBuild.addDays(actDay1.getDay());
                        break;
                    }
                }
                if (!redBuild.getFreeGift()) {
                    int[] giftArray = actDay1.getGiftArray();
                    for (int giftId : giftArray) {
                        if (buyGift.contains(giftId)) {
                            continue;
                        }

                        Shop shop = ShopManager.getShop(giftId);
                        if (shop.getPriceItemList().isEmpty()) {
                            hasRedPoint = true;
                            redBuild.setFreeGift(true);
                            break;
                        }
                    }
                }
            }
            if (hasRedPoint) {
                res_build.getActBuilder().putActDays(userAct.getActId(), redBuild.build());
            }
        }
        return hasRedPoint;
    }

}
